﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace vorkos_dev_snake
{
    public delegate void EventArgsMoved(Snake snake, Movement direction);
    [Serializable]
    public class GameLogic
    {
        private static int DEFAULTSPEED = 600;
        private const int SNAKESPEEDSTEP = 10;
        private int speed;
        private static readonly Object s_lock = new Object();
        private static GameLogic instance = null;
        public Boolean isGameOver;
        public IUserInterface UI { get; set; }

        public void IncreaseSpeed()
        {
            this.Speed -= SNAKESPEEDSTEP;
        }
        public static GameLogic Instance
        {
            get
            {
                if (instance != null) return instance;
                Monitor.Enter(s_lock);
                GameLogic temp = new GameLogic();
                Interlocked.Exchange(ref instance, temp);
                Monitor.Exit(s_lock);
                return instance;
            }
        }

        private GameLogic()
        {
            this.speed = DEFAULTSPEED;
            this.isGameOver = false;
        }
        public int Speed
        {
            get { return this.speed; }
            set
            {
                if (value >= 10) this.speed = value;
            }
        }
        public Boolean CheckCollision(Snake snake, Coordinate cell)
        {
            if (snake.GetSnakeCoordinates().First().Equals(cell))
            {
                return false;
            }
            if (snake.CurrentField.GetField().Contains(cell))
            {
                this.Stop();
                return true;
            }
            if (snake.GetSnakeCoordinates().Contains(cell))
            {
                this.Stop();
                return true;
            }
            return false;
        }

        internal bool CheckFood(Snake snake, Coordinate cell)
        {
            if (snake.CurrentField.GetFood() == null) return false;
            if (snake.CurrentField.GetFood().Contains(cell))
            {
                return true;
            }
            return false;
        }

        public void Start()
        {
            Random R = new Random();
            IUserInterface uiType = new ConsoleUI();
            this.UI = uiType;
            Field firstField = new Field();
            Snake snakePersonage = new Snake(firstField);
            this.UI.KeyPressed += UI_KeyPressed;
            //testing
            Menu.Instance.CallStartMenu();

            while (!this.isGameOver)
            {
                if (R.Next(15) == 1)
                {
                    Food newFood = new Food();
                    newFood.GenerateFood(snakePersonage);
                }
                if (!GameLogic.Instance.UI.ReadKey(snakePersonage)) GameLogic.Instance.Stop();
                Thread.Sleep(this.speed);
            }
        }

        public void UI_KeyPressed(Snake snake, Movement direction)
        {
            Snake snakePersonage = snake;
            snakePersonage.SetNewMove(snakePersonage, direction);
            GameLogic.Instance.UI.DrawSnake(snakePersonage, direction);
        }

        private void Stop()
        {
            this.isGameOver = true;
            this.UI.KeyPressed -= UI_KeyPressed;
            this.UI.GameOver();
            Thread.Sleep(3000);
        }

    }
}
